From 8522e94583477408704b779a5277aaa633e241ee Mon Sep 17 00:00:00 2001 From: Alex Williamson Date: Mon, 14 May 2007 11:52:01 -0600 Subject: [PATCH] [IA64] Fix ptc.ga emulation cset14829(c42ae7839750) was incomplete. The region register 0 will be clobbered as follows. time pcpu0 pcpu1 pcpu2 | vcpu0 vcpu1 idle // assignment of vcpu V 1.vcpu0 issues ptc.ga 2.vcpu0 sends IPI to vcpu1(pcpu1) 3.vcpu1 migrates from pcpu1 to pcpu2 4.pcpu1 receives IPI of 2 and exec ptc_ga_remote_func() 5.pcpu1 saves and modifies vrr[0] 6.vcpu1(pcpu2) modifies vrr[0] 7.pcpu1 restores vrr[0] // vrr[0] of 6 is lost Windows will crash due to this issue. Signed-off-by: Kouya Shimura --- xen/arch/ia64/vmx/vmmu.c | 42 +++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/xen/arch/ia64/vmx/vmmu.c b/xen/arch/ia64/vmx/vmmu.c index 4eb07ceef3..e6a6f376a2 100644 --- a/xen/arch/ia64/vmx/vmmu.c +++ b/xen/arch/ia64/vmx/vmmu.c @@ -563,11 +563,17 @@ struct ptc_ga_args { static void ptc_ga_remote_func (void *varg) { - u64 oldrid, moldrid, mpta, oldpsbits, vadr; + u64 oldrid, moldrid, mpta, oldpsbits, vadr, flags; struct ptc_ga_args *args = (struct ptc_ga_args *)varg; VCPU *v = args->vcpu; vadr = args->vadr; + /* Try again if VCPU has migrated. */ + if (v->processor != current->processor) + return; + vcpu_schedule_lock_irqsave(v, flags); + if (v->processor != current->processor) + goto bail; oldrid = VMX(v, vrr[0]); VMX(v, vrr[0]) = args->rid; oldpsbits = VMX(v, psbits[0]); @@ -584,6 +590,9 @@ static void ptc_ga_remote_func (void *varg) ia64_set_rr(0x0,moldrid); ia64_set_pta(mpta); ia64_dv_serialize_data(); + args->vcpu = NULL; +bail: + vcpu_schedule_unlock_irqrestore(v, flags); } @@ -602,28 +611,21 @@ IA64FAULT vmx_vcpu_ptc_ga(VCPU *vcpu, u64 va, u64 ps) if (!v->is_initialised) continue; - args.vcpu = v; -again: /* Try again if VCPU has migrated. */ - proc = v->processor; - if (proc != vcpu->processor) { - /* Flush VHPT on remote processors. */ - smp_call_function_single(v->processor, - &ptc_ga_remote_func, &args, 0, 1); - if (proc != v->processor) - goto again; - } else if (v == vcpu) { + if (v == vcpu) { vmx_vcpu_ptc_l(v, va, ps); - } else { - vcpu_schedule_lock_irq(v); + continue; + } + + args.vcpu = v; + do { proc = v->processor; - if (proc == vcpu->processor) - ptc_ga_remote_func(&args); + if (proc != vcpu->processor) + /* Flush VHPT on remote processors. */ + smp_call_function_single(proc, &ptc_ga_remote_func, + &args, 0, 1); else - proc = INVALID_PROCESSOR; - vcpu_schedule_unlock_irq(v); - if (proc == INVALID_PROCESSOR) - goto again; - } + ptc_ga_remote_func(&args); + } while (args.vcpu != NULL); } return IA64_NO_FAULT; } -- 2.30.2